package com.mec.offload.controller;

import cn.hutool.json.JSONObject;
import com.mec.offload.model.*;
import com.mec.offload.service.MecService;
import com.mec.offload.service.NodeTermService;
import com.mec.offload.service.OffloadSubTaskService;
import com.mec.offload.service.SubTaskService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.CrossOrigin;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;

import java.util.*;
import java.util.stream.Collectors;

@Controller
@RequestMapping("/offload/OffloadSubTask")
@CrossOrigin
public class OffloadSubTaskController {
    @Autowired
    private OffloadSubTaskService offloadSubTaskService;
    @Autowired
    private MecService mecService;
    @Autowired
    private NodeTermService nodeTermService;
    @Autowired
    private SubTaskService subTaskService;


    public class MecCount {
        int mecid;
        int count;
        public int getMecid(){return mecid;}
        public  int getCount(){return count;}
        public void setMecid(int mecid){this.mecid = mecid;}
        public void setCount(int count){this.count = count;}


    }

    //写offload数据库，将offmec全注册成1
    //@CrossOrigin(origins = "*")
    @RequestMapping("/addOffloadSubTask")
    @ResponseBody
    public int addOffload(Integer oriTaskId){
        try {
            List<SubTask>listS=subTaskService.getTaskByTaskOffload(oriTaskId);
            for(int i=0;i<listS.size();i++){
                OffloadSubTask offloadSubTask=new OffloadSubTask();
                offloadSubTask.setOffloadNum(listS.get(i).getSubTaskNum());
                offloadSubTask.setSubTaskId(listS.get(i).getSubTaskId());
                offloadSubTask.setOriTaskId(listS.get(i).getOriTaskId());
                offloadSubTask.setOriTermId(nodeTermService.getOriTaskTerm(oriTaskId).getTermId());
                offloadSubTask.setCostTran(0.0);
                offloadSubTask.setOffMecId(-1);
                offloadSubTask.setEnergyCost(0.0);
                offloadSubTaskService.addToOffloadTask(offloadSubTask);
            }
            return 1;
        }catch (Exception e){
            e.printStackTrace();
            return 0;
        }
    }

    //分配之前展示决策结果 展示所有offmec = -1 若大于等于5个就可进行卸载决策
    //列表展示 前5个功耗最高的
    //只按功耗排序
    //@CrossOrigin(origins = "*")
    @RequestMapping("/getAllBeforeOffloadTask")
    @ResponseBody
    public List<OffloadSubTask> getALL(){
        try{
            List<OffloadSubTask> listO;
            listO= offloadSubTaskService.getAllBeforeOffloadTask();
//            return listO;
            int []count=new int[5];
            count[0]=0;
            int j=1;
            for(int i=1;i<listO.size()&&j<5;i++)
                if(listO.get(i).getOriTermId()!=listO.get(i-1).getOriTermId())
                {
                    count[j]=i;
                    j++;
                }
            for(int i=1;i<j;i++)
                Collections.swap(listO,i,count[i]);
            return listO;
        }catch (Exception e){
            e.printStackTrace();
            return null;
        }
    }

    //给学姐 未排序
    //topo展示 所有已经分配了的offmec！=-1
    //@CrossOrigin(origins = "*")
    @RequestMapping("/getAllAfterOffloadTask")
    @ResponseBody
    public List<OffloadSubTask> getAfter(){
        try {
            return offloadSubTaskService.getAllAfterOffloadTask();
        }catch (Exception e){
            e.printStackTrace();
            return null;
        }
    }

    //匈牙利算法部分
    //@CrossOrigin(origins = "*")
    @RequestMapping("/MecMapping")
    @ResponseBody
    public int MecMapping(){
        try{
            List<OffloadSubTask> list = offloadSubTaskService.getAllBeforeOffloadTask();
            List<OffloadSubTask> listO = list.stream().sorted(Comparator.comparing(OffloadSubTask::getEnergyCost))
                    .collect(Collectors.toList());
            Collections.reverse(listO);
            int[][] CostTran=new int[5][5];
            List<MEC>listM=mecService.getAllMec();
            Double E_up=0.0;
            for(int i=0;i<5;i++){
                NodeTerm nodeTerm=nodeTermService.getOriTaskTerm(listO.get(i).getOriTaskId());
                SubTask subTask=subTaskService.getSubTaskById(listO.get(i).getSubTaskId());
                for(int j=0;j<listM.size();j++){
                    Double t1=subTask.getSubTaskBite()
                            /nodeTerm.getDataTranRate();
                    Double t_exe=subTask.getSubTaskRes()/listM.get(j).getMecRate();
                    Double L_up=t1+t_exe;
                    E_up=t1
                            * nodeTerm.getTermTranPower()/1000
                            +listM.get(j).getConnectPower()
                            *t_exe;
                    CostTran[i][j] = (int) Math.round(-(L_up+E_up)/2);
                }//代价矩阵初始化
            }
            KM newMap=new KM(CostTran);
            newMap.km();
            int[] match=newMap.getMatch();
            for(int i=0;i<match.length;i++){
                listO.get(i).setCostTran((double) -CostTran[i][match[i]]);
                listO.get(i).setOffMecId(match[i]+1);
                listO.get(i).setEnergyCost(-CostTran[i][match[i]]*1.8);
                offloadSubTaskService.updateOffloadTask(listO.get(i));
                //更新吞吐量
                nodeTermService.updateThroughPut(listO.get(i));
            }
            return 1;
        }catch (Exception e){
            e.printStackTrace();
            return -1;
        }
    }


    //docin
    //分配之前展示决策结果 展示所有offmec = -1 若大于等于5个就可进行卸载决策
    //列表展示 前5个功耗最高的
    //只按功耗排序
    //@CrossOrigin(origins = "*")
    @RequestMapping("/getAllBeforeOffloadTaskdou")
    @ResponseBody
    public String getALLdou(){
        try{
            List<OffloadSubTask> list0;
            list0 = offloadSubTaskService.getAllBeforeOffloadTask();
//            List<OffloadSubTask> listO = list.stream().sorted(Comparator.comparing(OffloadSubTask::getEnergyCost))
//                    .collect(Collectors.toList());
//            Collections.reverse(listO);

            JSONObject jo = new JSONObject();
            jo.put("code",0);
            jo.put("msg","");
            jo.put("count",list0.size());
            jo.put("data", list0);
            return jo.toString();
        }catch (Exception e){
            e.printStackTrace();
            return null;
        }
    }


    //匈牙利算法部分
    //点击确定分配mec，并返回给学姐topo
    //@CrossOrigin(origins = "*")
    @RequestMapping("/MecMappingdou")
    @ResponseBody
    public List<OffloadSubTask> MecMappingdou(){
        try{
            List<OffloadSubTask> list0 = offloadSubTaskService.getAllBeforeOffloadTask();
//            List<OffloadSubTask> listO = list.stream().sorted(Comparator.comparing(OffloadSubTask::getEnergyCost))
//                    .collect(Collectors.toList());
//            Collections.reverse(listO);
            int[][] CostTran=new int[5][5];
            List<MEC>listM=mecService.getAllMec();
            Double E_up=0.0;
            for(int i=0;i<5;i++){
                NodeTerm nodeTerm=nodeTermService.getOriTaskTerm(list0.get(i).getOriTaskId());
                SubTask subTask=subTaskService.getSubTaskById(list0.get(i).getSubTaskId());
                for(int j=0;j<listM.size();j++){
                    Double t1=subTask.getSubTaskBite()
                            /nodeTerm.getDataTranRate();
                    Double t_exe=subTask.getSubTaskRes()/listM.get(j).getMecRate();
                    Double L_up=t1+t_exe;
                    E_up=t1
                            * nodeTerm.getTermTranPower()/1000
                            +listM.get(j).getConnectPower()
                            *t_exe;
                    CostTran[i][j] = (int) Math.round(-(L_up+E_up)/2);
                }//代价矩阵初始化
            }
            KM newMap=new KM(CostTran);
            newMap.km();
            int[] match=newMap.getMatch();
            for(int i=0;i<match.length;i++){
                list0.get(i).setCostTran((double) -CostTran[i][match[i]]);
                list0.get(i).setOffMecId(match[i]+1);
                list0.get(i).setEnergyCost(-CostTran[i][match[i]]*1.8);
                offloadSubTaskService.updateOffloadTask(list0.get(i));
                //更新吞吐量
                nodeTermService.updateThroughPut(list0.get(i));
            }
            System.out.println(list0.size());
            iteratorRemove(list0,-1);
            return list0;
        }catch (Exception e){
            e.printStackTrace();
            return null;
        }
    }

    public static List iteratorRemove(List list, Integer elemennt) {
        Iterator<OffloadSubTask> iterator = list.iterator();
        while (iterator.hasNext()) {
            OffloadSubTask cur = iterator.next();
            if (cur.getOffMecId().equals(elemennt)) {
                // 注意！！！这里时Iterator.remove()!!!而不是list.remove()!!!
                iterator.remove();
            }
        }
        return list;
    }

    //layui表格展示
    //所有已经分配了的offmec！=-1
    //@CrossOrigin(origins = "*")
    @RequestMapping("/getAllAfterOffloadTaskdou")
    @ResponseBody
    public String getAfterdou(@RequestParam(required=false,defaultValue="1") int page,
                              @RequestParam(required=false,defaultValue="10") int limit){
        try {
            List<OffloadSubTask> list = offloadSubTaskService.getoffall(page,limit);
            List<OffloadSubTask> listO = list.stream().sorted(Comparator.comparing(OffloadSubTask::getSubTaskId))
                    .collect(Collectors.toList());
            int countx=  offloadSubTaskService.queryAllCount();
            JSONObject jo = new JSONObject();
            jo.put("code",0);
            jo.put("msg","");
            jo.put("count", countx);
            jo.put("data", listO);
            return jo.toString();
        }catch (Exception e){
            e.printStackTrace();
            return null;
        }
    }

    //给学姐 按数量聚合排序版本
    //topo展示 所有已经分配了的offmec！=-1
    //@CrossOrigin(origins = "*")
    @RequestMapping("/getAllAfterOffloadTaskdd")
    @ResponseBody
    public List<MecCount> getAfterdd(){
        try {
            List<OffloadSubTask> list = offloadSubTaskService.getAllAfterOffloadTask();
            int []s=new int[5];
            for (int i = 0; i < list.size(); i++) {
                s[list.get(i).getOffMecId()-1]+=1;
            }
            List<MecCount> mecl = new ArrayList<>() ;
            for (int i = 0; i < 5; i++) {
                mecl.add(new MecCount());
            }
            mecl.get(0).setMecid(1);
            mecl.get(1).setMecid(2);
            mecl.get(2).setMecid(3);
            mecl.get(3).setMecid(4);
            mecl.get(4).setMecid(5);
            mecl.get(0).setCount(s[0]);
            mecl.get(1).setCount(s[1]);
            mecl.get(2).setCount(s[2]);
            mecl.get(3).setCount(s[3]);
            mecl.get(4).setCount(s[4]);
            List<MecCount> mec0;
            mec0 = mecl.stream().sorted(Comparator.comparing(MecCount::getCount))
                    .collect(Collectors.toList());
            List<OffloadSubTask>list0 = new ArrayList<>();
            for (int i = 0; i < list.size(); i++) {
                if(list.get(i).getOffMecId().equals(mec0.get(0).getMecid())){
                    list0.add(list.get(i));
                }
            }
            for (int i = 0; i < list.size(); i++) {
                if(list.get(i).getOffMecId().equals(mec0.get(1).getMecid())){
                    list0.add(list.get(i));
                }
            }
            for (int i = 0; i < list.size(); i++) {
                if(list.get(i).getOffMecId().equals(mec0.get(2).getMecid())){
                    list0.add(list.get(i));
                }
            }
            for (int i = 0; i < list.size(); i++) {
                if(list.get(i).getOffMecId().equals(mec0.get(3).getMecid())){
                    list0.add(list.get(i));
                }
            }
            for (int i = 0; i < list.size(); i++) {
                if(list.get(i).getOffMecId().equals(mec0.get(4).getMecid())){
                    list0.add(list.get(i));
                }
            }
              return mec0;
        }catch (Exception e){
            e.printStackTrace();
            return null;
        }
    }

    //获取每个mec上已有的子任务
    //@CrossOrigin(origins = "*")
    @RequestMapping("/getmecoffs")
    @ResponseBody
    public String getmecoffsdou(Integer offMecId,@RequestParam(required=false,defaultValue="1") int page,
                                @RequestParam(required=false,defaultValue="10") int limit){
        List<OffloadSubTask> list0 = offloadSubTaskService.getmecoffs(offMecId,page,limit);
        int countx = offloadSubTaskService.querymecAllCount(offMecId);
        JSONObject jo = new JSONObject();
        jo.put("code",0);
        jo.put("msg","");
        jo.put("count",countx);
        jo.put("data", list0);
        return jo.toString();
    }

    //http://localhost:7000/offload/OffloadSubTask/resetAllOffloadTasks
    @RequestMapping("/resetAllOffloadTasks")
    @ResponseBody
    public void resetAllOffloadTasks() {
        offloadSubTaskService.resetAllOffloadTasks();
    }


}
